import axios from 'axios';
import qs from 'qs';
import { get, defaults, isNumber, isString } from 'lodash';
import message from '@/utils/Message';
import masking from '@/utils/Masking';
// axios 请求配置
import { requestConfig, tokenName } from '@/setting';
import userCookies from '@/utils/data/cookies';
const service = axios.create({
    // baseURL: process.env.VUE_APP_BASEURL
});
import '@/mock';

// 拦截请求
service.interceptors.request.use(
    (config: any) => {
        // #todo 或许可以把这一段代码逻辑调整到axiosRequest中
        const { cookies = [] } = config;
        let data = config.data;
        // 请求体额外携带的cookie数据
        if (cookies.length) {
            if (!data) {
                data = {};
            }
            cookies.forEach((item: string) => {
                data[item] = userCookies.get(item);
            });
        }
        if (data) {
            const isJson = config.isJson;
            let contentYype = 'application/x-www-form-urlencoded;charset=UTF-8';
            if (isJson) {
                contentYype = 'application/json';
            }
            config.headers['Content-Type'] = contentYype;
            config.data = isJson ? JSON.stringify(data) : qs.stringify(data);
        }
        const token = userCookies.get();
        if (config.isToken && !config.headers[tokenName] && token) {
            // data[tokenName] = `${token}`;
            config.headers[tokenName] = `${token}`;
        }

        // 展示请求遮罩
        masking.loading(config.loading);
        // 展示请求遮罩
        return config;
    },
    (error) => {
        return Promise.reject(error);
    }
);
// 拦截请求结果
service.interceptors.response.use(
    (res: any) => {
        // 隐藏请求遮罩
        masking.clear(res.config.loading);
        return res;
    },
    (thrown) => {
        const { response } = thrown;
        if (response) {
            // 隐藏请求遮罩
            masking.clear(response.config.loading);
        } else {
            // 超时等情况直接关闭所有遮罩
            masking.clearAll();
        }
        return Promise.reject();
    }
);

/**
 *  基础提交数据函数
 *  成功失败都有回调
 *
 * @export
 * @param {*} data axios配置
 * @param {*} [{
 *     successCode = requestConfig.successValue, 请求成功状态码
 *     successProperty = requestConfig.successProperty, 请求成功状态码字段名词
 *     successMessage = false, 请求成功是否显示提示信息 false 不显示 ,ture 显示服务端消息，string 显示自定义消息
 *
 *     errorMessage = true, 请求失败是否显示提示信息 false 不显示 ,ture 显示服务端消息，string 显示自定义消息
 *
 *     loading = true, 请求时是否显示加载遮罩，false 不显示 ,ture 显示
 *     可传大于0的数字（单位毫秒）,默认值为100，加载遮罩延时消失时间。
 *     请求结束后，在指定时间内再次发出请求，可保证遮罩连续显示
 *     isToken = true, 是否带Token
 *     cookies = [] 请求体额外携带的cookie数据
 *
 *     isJson = false 请求数据在data中时是否为json格式
 *     ...config axios配置
 * }={}]
 * @return {*} Promise
 */
export function axiosRequest(
    uxData: any,
    {
        successCode = requestConfig.successValue,
        successProperty = requestConfig.successProperty,
        successMessage = false,
        errorMessage = true,
        loading = true,
        isToken = true,
        isJson = true,
        ...config
    }: any = {}
): any {
    return new Promise((resolve, reject) => {
        // 如果有遮罩提示消息
        if (loading) {
            let nextTime = 100;
            if (isNumber(loading) && loading > 0) {
                nextTime = loading;
            }
            // 设置遮罩配置
            uxData.loading = {
                nextTime: nextTime,
                // 当前请求所在视图名称(这里固定名词，做全局遮罩)
                view: 'all'
            };
        }
        // 如果有遮罩提示消息
        // 标识是否带Token
        uxData.isToken = isToken;
        // 标识请求数据在data中时是否为json格式
        if (uxData.data) {
            uxData.isJson = isJson;
        }
        // 写入axios配置
        defaults(uxData, config);
        // console.log(process.env.DEPLOY);
        service
            .request(uxData)
            .then((res) => {
                const data = res.data,
                    code = get(data, successProperty);
                if (code != requestConfig.maintenanceCode) {
                    // 判断提交数据结果
                    const success = code == successCode;
                    // 标识请求结果状态
                    data.success = success;
                    // 获取接口返回提示信息
                    let mes = get(data, requestConfig.messageProperty);
                    if (successMessage && success) {
                        // 如果请求成功并且 successMessage 有值
                        // 如果 successMessage 是字符串类型，那么提示信息为 successMessage ，否则为接口返回提示信息
                        mes = isString(successMessage) ? successMessage : mes;
                    } else if (errorMessage && !success) {
                        // 如果请求失败并且 errorMessage 有值
                        // 如果 errorMessage 是字符串类型，那么提示信息为 errorMessage ，否则为接口返回提示信息
                        mes = isString(errorMessage) ? errorMessage : mes;
                    } else {
                        // 其他情况下不显示提示信息
                        mes = '';
                    }
                    // 如果提示消息有值则显示提示消息
                    if (mes) {
                        // 确定消息提示类型
                        const type = success ? 'success' : 'error';
                        message.show(mes, type);
                    }
                    if (success) {
                        resolve(res);
                    } else {
                        reject(data);
                    }
                }
                // 标识请求完成
                uxData.loadingEnd = true;
                // console.log(uxData);
            })
            .catch(() => {
                // console.log(uxData);
                // 标识请求完成
                uxData.loadingEnd = true;
                // 请求失败
                reject({
                    success: false,
                    data: null
                });
            });
    });
}

/**
 * 提交数据函数
 *
 * @export
 * @param {*} data axios配置
 * @param {*} options 同axiosRequest options 配置
 * @return {*} Promise
 */
export function requestBack(data: any, options: any): any {
    return new Promise((resolve, reject) => {
        axiosRequest(data, options)
            .then((res: any) => {
                // 一般来说前端只需要res.data中的数据
                resolve(res.data);
            })
            .catch((res: any) => {
                reject(res);
            });
    });
}

/**
 * get 方式提交数据
 *
 * @export
 * @param {*} url 地址
 * @param {*} params 参数
 * @param {*} [{
 *     method = "get", 请求模式，#todo 预留扩展，请勿设置
 *     ...options 同axiosRequest options 配置
 * }={}]
 * @return {*} Promise
 */
export function ajaxBack(
    url: any,
    params: any,
    { method = 'get', ...options }: any = {}
): any {
    return requestBack(
        {
            url,
            method,
            params
        },
        options
    );
}

/**
 * get 方式提交数据
 * 忽略catch
 * @export
 * @param {*} url 地址
 * @param {*} params 参数
 * @param {*} options 同axiosRequest options 配置
 * @return {*} Promise
 */
export function ajax(url: any, params?: any, options: any = {}): any {
    return new Promise((resolve) => {
        ajaxBack(url, params, options)
            .then((res: any) => {
                resolve(res);
            })
            .catch(() => {});
    });
}

/**
 * post 方式提交数据
 *
 * @export
 * @param {*} url 地址
 * @param {*} params 参数
 * @param {*} [{
 *     method = "post", 请求模式，#todo 预留扩展，请勿设置
 *     ...options 同axiosRequest options 配置
 * }={}]
 * @return {*} Promise
 */
export function ajaxPostBack(
    url: any,
    params?: any,
    { method = 'post', ...options }: any = {}
): any {
    return requestBack(
        {
            url,
            method,
            // #todo 后期可调整 axiosRequest 实现统一用params
            data: params
        },
        options
    );
}

/**
 * POST 方式提交数据
 * 忽略catch
 *
 * @export
 * @param {*} url 地址
 * @param {*} params 参数
 * @param {*} options 同axiosRequest options 配置
 * @return {*} Promise
 */
export function ajaxPost(url: any, params?: any, options: any = {}): any {
    return new Promise((resolve) => {
        ajaxPostBack(url, params, options)
            .then((res: any) => {
                resolve(res);
            })
            .catch(() => {});
    });
}

export function download(
    url: any,
    params = {},
    fileName = '',
    { method = 'get', ...options }:any = {}
) {
    const data: any = {
        url,
        method,
        responseType: 'blob',
        isToken: true,
        ...options
    };
    if (method == 'get') {
        data.params = params;
    } else {
        data.data = params;
    }
    service.request(data).then(({ data }) => {
        console.log(data);
        if (data.type != 'application/json') {
            if (data.size) {
                const link = document.createElement('a');
                const blob = new Blob([data], { type: data.type });
                link.style.display = 'none';
                link.href = URL.createObjectURL(blob);
                if (fileName) {
                    // 下载的文件名
                    link.download = fileName;
                }
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
            } else {
                message.warning('暂无可导出数据');
            }
        } else {
            message.warning('导出失败');
        }
    });
}

export default {};
